﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using QldtSdh.DAL.Models;
using QldtSdh.GUI.DuLieu;
using QldtSdh.Utils;

namespace QldtSdh.BLL
{
    public partial class BizLopHocPhan
    {
        /// <summary>
        /// Lấy danh sách lớp học phần trong 1 một học kỳ thuộc 1 đơn vị nào đó. 
        /// Danh sách được sắp xếp theo tên lớp khoá ngành tham chiếu -> tên lớp học phần -> tính bắt buộc
        /// Có chứa thông tin HocPhan
        /// </summary>
        /// <param name="maHocKy"></param>
        /// <param name="maDonViPhuTrach"></param>
        /// <returns></returns>
        internal static List<LopHocPhan> GetListOrderByTenLopHocPhan(string maHocKy, string maDonViPhuTrach,
            bool hienThiHocPhanBatBuocTruoc = false, CEMS4UG_DHKHContext db = null)
        {
            if (db == null)
                using (var db2 = CEMS4UG_DHKHContext.GetContext()) { return GetListOrderByTenLopHocPhan(maHocKy, maDonViPhuTrach, hienThiHocPhanBatBuocTruoc, db2); }
            else
            {
                List<LopHocPhan> lstLopHocPhan = null;
                lstLopHocPhan = db.LopHocPhanDbSet
                .Include("HocPhan")
                .Where(e => e.MaHocKyGUID == maHocKy && e.HocPhan.MaDonViPhuTrachGUID == maDonViPhuTrach)
                .ToList();
                foreach (var lopHocPhan in lstLopHocPhan)
                {
                    var lopKhoaNganhThamChieu = db.LopKhoaNganhDbSet
                        .Include("KhoaHoc_NganhDaoTao")
                        .Where(e => e.MaLopKhoaNganhGUID == lopHocPhan.MaLopKhoaNganhThamChieu).FirstOrDefault();
                    if (lopKhoaNganhThamChieu != null)
                    {
                        lopHocPhan._LopKhoaNganhThamChieu = lopKhoaNganhThamChieu;
                        lopHocPhan._TenLopKhoaNganhThamChieu = lopKhoaNganhThamChieu.TenLopKhoaNganh;
                        var maChuongTrinhDaoTaoGUID = lopKhoaNganhThamChieu.KhoaHoc_NganhDaoTao.MaChuongTrinhDaoTaoGUID;
                        var hocPhanTrongChuonGtrinhDaoTao = db.ChuongTrinhDaoTao_HocPhanDbSet.Where(e =>
                            e.MaChuongTrinhDaoTaoGUID == maChuongTrinhDaoTaoGUID &&
                            e.MaHocPhan == lopHocPhan.MaHocPhanGUID).FirstOrDefault();
                        if (hocPhanTrongChuonGtrinhDaoTao != null)
                            lopHocPhan._LaHocPhanBatBuocCuaLopKhoaNganhTrongCTDT = hocPhanTrongChuonGtrinhDaoTao.LaHocPhanBatBuoc;
                        else
                            lopHocPhan._LaHocPhanBatBuocCuaLopKhoaNganhTrongCTDT = true;
                    }
                    else
                    {
                        lopHocPhan._LopKhoaNganhThamChieu = null;
                        lopHocPhan._TenLopKhoaNganhThamChieu = "";
                        lopHocPhan._LaHocPhanBatBuocCuaLopKhoaNganhTrongCTDT = true;
                    }
                }

                if (hienThiHocPhanBatBuocTruoc)
                    return lstLopHocPhan
                        .OrderBy(e => e.TenLopHocPhan)
                        //.ThenBy(e => e._TenLopKhoaNganhThamChieu)
                        //.ThenByDescending(e => e._LaHocPhanBatBuocCuaLopKhoaNganhTrongCTDT)
                        .ToList();
                else
                    return lstLopHocPhan
                        .OrderBy(e => e.TenLopHocPhan)
                        //.OrderBy(e => e._TenLopKhoaNganhThamChieu)
                        .ToList();

            }
        }

        /// <summary>
        /// Xoá lớp học phần rỗng khỏi hệ thống
        /// </summary>
        /// <param name="maLopHocPhan"></param>
        /// <param name="db"></param>
        internal static void XoaLopHocPhanRong(string maLopHocPhan, CEMS4UG_DHKHContext db = null)
        {
            if (db == null)
                using (var db2 = CEMS4UG_DHKHContext.GetContext()) { XoaLopHocPhanRong(maLopHocPhan, db2); }
            else
            {
                var lopHocPhan = db.LopHocPhanDbSet.Where(e => e.MaLopHocPhanGUID == maLopHocPhan).FirstOrDefault();
                if (lopHocPhan == null)
                    throw new Exception("Lớp học phần không còn tồn tại trên hệ thống");
                var nHocVien = db.LopHocPhan_HocVienDbSet.Count(e => e.MaLopHocPhanGUID == maLopHocPhan);
                if (nHocVien > 0)
                    throw new Exception(string.Format("Còn {0} học viên trong lớp học phần", nHocVien));
                var nPCGD = db.LopHocPhan_PhanCongGiangDayDbSet.Count(e => e.MaLopHocPhanGUID == maLopHocPhan);
                if (nPCGD > 0)
                    throw new Exception(string.Format("Chưa xoá phân công giảng dạy cho lớp học phần"));
                var nDotThi = db.DotThi_LopHocPhanDbSet.Count(e => e.MaLopHocPhanGUID == maLopHocPhan);
                if (nDotThi > 0)
                    throw new Exception("Lớp thi còn tham vào đợt thi trong học kỳ");
                db.LopHocPhanDbSet.Remove(lopHocPhan);
                BizNhatKyHoatDong.LogAndCommitDelete2(lopHocPhan, maLopHocPhan, LOAIDOITUONG.LỚP_HỌC_PHẦN, db);
            }
        }

        /// <summary>
        /// Cập nhật thông tin cơ bản của lớp học phần
        /// </summary>
        /// <param name="maLopHocPhanGUID"></param>
        /// <param name="tenLopHocPhan"></param>
        /// <param name="hinhThucHoc"></param>
        /// <param name="hinhThucThi"></param>
        /// <param name="heSoDiemQTHT"></param>
        /// <param name="db"></param>
        internal static void Update(string maLopHocPhanGUID, string tenLopHocPhan, string hinhThucHoc,
            string hinhThucThi, int heSoDiemQTHT, CEMS4UG_DHKHContext db = null)
        {
            if (db == null)
                using (var db2 = CEMS4UG_DHKHContext.GetContext()) { Update(maLopHocPhanGUID, tenLopHocPhan, hinhThucHoc, hinhThucThi, heSoDiemQTHT, db2); }
            else
            {
                var lopHocPhan = db.LopHocPhanDbSet.Where(e => e.MaLopHocPhanGUID == maLopHocPhanGUID).FirstOrDefault();
                if (lopHocPhan == null)
                    throw new Exception("Lớp học phần không còn tồn tại trên hệ thống");

                var oldLopHocPhan = new LopHocPhan()
                {
                    MaLopHocPhanGUID = lopHocPhan.MaLopHocPhanGUID,
                    TenLopHocPhan = lopHocPhan.TenLopHocPhan,
                    HinhThucHoc = lopHocPhan.HinhThucHoc,
                    HinhThucThi = lopHocPhan.HinhThucThi,
                    HeSoDiemQTHT = lopHocPhan.HeSoDiemQTHT
                };

                lopHocPhan.TenLopHocPhan = tenLopHocPhan;
                lopHocPhan.HinhThucHoc = hinhThucHoc;
                lopHocPhan.HinhThucThi = hinhThucThi;
                lopHocPhan.HeSoDiemQTHT = heSoDiemQTHT;

                BizNhatKyHoatDong.LogAndCommitUpdate2(oldLopHocPhan, lopHocPhan, lopHocPhan.MaLopHocPhanGUID, LOAIDOITUONG.LỚP_HỌC_PHẦN, db);
            }
        }

        /// <summary>
        /// Danh sách học viên đăng ký lớp học phần
        /// Dữ liệu chi tiết: HocVien
        /// </summary>
        /// <param name="maLopHocPhanGUID"></param>
        /// <param name="db"></param>
        /// <returns></returns>
        internal static List<LopHocPhan_HocVien> GetListDangKyLopHocPhan(string maLopHocPhanGUID, CEMS4UG_DHKHContext db = null)
        {
            if (db == null)
                using (var db2 = CEMS4UG_DHKHContext.GetContext()) { return GetListDangKyLopHocPhan(maLopHocPhanGUID, db2); }
            else
            {
                var lstDangKyLopHocPhan = db.LopHocPhan_HocVienDbSet
                    .Include("HocVien")
                    .Where(e => e.MaLopHocPhanGUID == maLopHocPhanGUID)
                    .OrderBy(e => e.HocVien.Ten)
                    .ThenBy(e => e.HocVien.HoDem)
                    .ToList();
                return lstDangKyLopHocPhan;
            }
        }

        /// <summary>
        /// Rút đăng ký học viên "maHocVien" ra khỏi lớp học phần "maLopHocPhanGUID"
        /// </summary>
        /// <param name="maLopHocPhanGUID"></param>
        /// <param name="maHocVien"></param>
        /// <param name="db"></param>
        internal static void RutDangKyHocVien(string maLopHocPhanGUID, string maHocVien, CEMS4UG_DHKHContext db = null)
        {
            if (db == null)
                using (var db2 = CEMS4UG_DHKHContext.GetContext()) { RutDangKyHocVien(maLopHocPhanGUID, maHocVien, db2); }
            else
            {
                var x = db.LopHocPhan_HocVienDbSet.Where(e => e.MaLopHocPhanGUID == maLopHocPhanGUID && e.MaHocVien == maHocVien).FirstOrDefault();
                if (x == null)
                    throw new Exception("Thông tin đăng ký học viên không còn tồn tại trên hệ thống");
                db.LopHocPhan_HocVienDbSet.Remove(x);
                BizNhatKyHoatDong.LogAndCommitDelete2<LopHocPhan_HocVien>(x, x.MaLopHocPhan_HocVienGUID, LOAIDOITUONG.LỚP_HỌC_PHẦN_HỌC_VIÊN, db);
            }
        }

        /// <summary>
        /// Rút đăng ký học viên trong danh sách lstLopHocPhan_HocVien ra khỏi lớp học phần "maLopHocPhanGUID"
        /// </summary>
        /// <param name="maLopHocPhanGUID"></param>
        /// <param name="maHocVien"></param>
        /// <param name="db"></param>
        internal static void RutDangKyHocVien(string maLopHocPhanGUID, List<LopHocPhan_HocVien> lstLopHocPhan_HocVien, CEMS4UG_DHKHContext db = null)
        {
            if (db == null)
                using (var db2 = CEMS4UG_DHKHContext.GetContext()) { RutDangKyHocVien(maLopHocPhanGUID, lstLopHocPhan_HocVien, db2); }
            else
            {
                using (var trans = db.Database.BeginTransaction())
                {
                    try
                    {
                        foreach (var x in lstLopHocPhan_HocVien)
                            RutDangKyHocVien(maLopHocPhanGUID, x.MaHocVien, db);
                        trans.Commit();
                    }
                    catch (Exception exc)
                    {
                        trans.Rollback();
                        throw exc;
                    }
                }
            }
        }

        /// <summary>
        /// Tạo mới lớp học phần và chuyển các học viên sang học phần mới
        /// </summary>
        /// <param name="lstLopHocPhan_HocVien"></param>
        /// <param name="lopHocPhanGoc"></param>
        /// <param name="db"></param>
        internal static void ChuyenHocVienSangLopMoi(List<LopHocPhan_HocVien> lstLopHocPhan_HocVien,
            LopHocPhan lopHocPhanGoc, CEMS4UG_DHKHContext db = null)
        {
            if (db == null)
                using (var db2 = CEMS4UG_DHKHContext.GetContext()) { ChuyenHocVienSangLopMoi(lstLopHocPhan_HocVien, lopHocPhanGoc, db2); }
            else
                using (var trans = db.Database.BeginTransaction())
                {
                    try
                    {
                        // 2.1 Nhập thông tin lớp học phần mới
                        var hocKy = BizHocKy.GetByMaHocKyGUID(lopHocPhanGoc.MaHocKyGUID, db);
                        var hocPhan = lopHocPhanGoc.HocPhan;
                        string prefix = string.Format("{0}.{1}.{2}.",
                            hocKy.NamHoc, hocKy.SoThuTuHocKy, hocPhan.MaHocPhan);
                        #region string maLopHocPhanMoi = ...;
                        string maLopHocPhanMoi = "";
                        var idx = 1;
                        while (true)
                        {
                            maLopHocPhanMoi = prefix + StringUtils.Thousandize(idx);
                            if (BizDaoTao.DaTonTaiMaLopHocPhan(maLopHocPhanMoi, db))
                            {
                                idx++;
                                if (idx >= 1000)
                                    throw new Exception("Có lỗi bất thường. Không thể thử tạo được 1000 lớp học phần trên cơ sở dữ liệu.");
                            }
                            else
                                break;
                        }
                        if (string.IsNullOrEmpty(maLopHocPhanMoi))
                            throw new Exception("Có lỗi bất thường. Không thể tạo ra mã lớp học phần được.");
                        #endregion

                        // 2.2. Tạo lớp học phần mới theo thông tin từ lớp học phần gốc
                        #region var lopHocPhanMoi = ...;
                        var lopHocPhanMoi = new LopHocPhan()
                                        {
                                            MaLopHocPhanGUID = maLopHocPhanMoi,
                                            MaHocKyGUID = lopHocPhanGoc.MaHocKyGUID,
                                            MaHocPhanGUID = lopHocPhanGoc.MaHocPhanGUID,
                                            MaLopKhoaNganhThamChieu = lopHocPhanGoc.MaLopKhoaNganhThamChieu,
                                            NgayBatDau = lopHocPhanGoc.NgayBatDau,
                                            NgayBatDauDuKien = lopHocPhanGoc.NgayBatDauDuKien,
                                            NgayKetThuc = lopHocPhanGoc.NgayKetThuc,
                                            NgayKetThucDuKien = lopHocPhanGoc.NgayKetThucDuKien,
                                            TinhTrang = lopHocPhanGoc.TinhTrang,
                                            TenLopHocPhan = lopHocPhanGoc.TenLopHocPhan + string.Format(" (copy {0})", DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss")),
                                            HinhThucHoc = lopHocPhanGoc.HinhThucHoc,
                                            HinhThucThi = lopHocPhanGoc.HinhThucThi,
                                            HeSoDiemQTHT = lopHocPhanGoc.HeSoDiemQTHT
                                        };
                        #endregion
                        db.LopHocPhanDbSet.Add(lopHocPhanMoi);
                        BizNhatKyHoatDong.LogAndCommitInsert2<LopHocPhan>(lopHocPhanMoi, lopHocPhanMoi.MaLopHocPhanGUID, LOAIDOITUONG.LỚP_HỌC_PHẦN, db);

                        // 3. Thực hiện danh sách học viên từ lớp học phần gốc sang lớp học phần mới
                        foreach (var x in lstLopHocPhan_HocVien)
                        {
                            #region chuyển học viên x từ lớp gốc sang lớp mới
                            var oX = db.LopHocPhan_HocVienDbSet.Where(
                                                    e => e.MaLopHocPhanGUID == x.MaLopHocPhanGUID && e.MaHocVien == x.MaHocVien)
                                                    .FirstOrDefault();
                            if (oX == null)
                                continue;

                            db.LopHocPhan_HocVienDbSet.Remove(oX);
                            var oX2 = new LopHocPhan_HocVien()
                            {
                                MaLopHocPhanGUID = maLopHocPhanMoi,
                                MaHocVien = x.MaHocVien,
                                HocThayThe = x.HocThayThe,
                                DiemQTHT = x.DiemQTHT,
                                LanHoc = x.LanHoc,
                                MaHocPhanGUID_ThayThe = x.MaHocPhanGUID_ThayThe
                            };
                            db.LopHocPhan_HocVienDbSet.Add(oX2);
                            #endregion

                            BizNhatKyHoatDong.LogAndCommitUpdate2(oX, oX2, oX.MaHocVien, LOAIDOITUONG.LỚP_HỌC_PHẦN_HỌC_VIÊN, db);
                        }

                        // 4. Commit
                        trans.Commit();
                    }
                    catch (Exception exc)
                    {
                        trans.Rollback();
                        throw exc;
                    }
                }
        }

        /// <summary>
        /// Chuyển toàn bộ học viên từ lớp này sang lớp khác
        /// </summary>
        /// <param name="tuLopHocPhan"></param>
        /// <param name="denLopHocPhan"></param>
        /// <param name="db"></param>
        internal static void ChuyenHocVienSangLopKhac(LopHocPhan tuLopHocPhan, LopHocPhan denLopHocPhan, CEMS4UG_DHKHContext db = null)
        {
            ChuyenHocVienSangLopKhac(tuLopHocPhan.LopHocPhan_HocVien, denLopHocPhan, db);
        }

        /// <summary>
        /// Chuyển một số học viên từ lớp này sang lớp khác
        /// </summary>
        /// <param name="lstLopHocPhan_HocVien"></param>
        /// <param name="denLopHocPhan"></param>
        /// <param name="db"></param>
        internal static void ChuyenHocVienSangLopKhac(ICollection<LopHocPhan_HocVien> lstLopHocPhan_HocVien,
            LopHocPhan denLopHocPhan, CEMS4UG_DHKHContext db = null)
        {
            if (db == null)
                using (var db2 = CEMS4UG_DHKHContext.GetContext())
                    ChuyenHocVienSangLopKhac(lstLopHocPhan_HocVien, denLopHocPhan, db2);
            else
            {
                using (var trans = db.Database.BeginTransaction())
                {
                    try
                    {
                        foreach (var x in lstLopHocPhan_HocVien)
                        {
                            var oX = db.LopHocPhan_HocVienDbSet.Where(
                                e => e.MaLopHocPhanGUID == x.MaLopHocPhanGUID && e.MaHocVien == x.MaHocVien)
                                .FirstOrDefault();
                            if (oX != null)
                            {
                                db.LopHocPhan_HocVienDbSet.Remove(oX);

                                var oX2 = new LopHocPhan_HocVien()
                                {
                                    MaLopHocPhanGUID = denLopHocPhan.MaLopHocPhanGUID,
                                    MaHocVien = x.MaHocVien,
                                    HocThayThe = x.HocThayThe,
                                    DiemQTHT = x.DiemQTHT,
                                    LanHoc = x.LanHoc,
                                    MaHocPhanGUID_ThayThe = x.MaHocPhanGUID_ThayThe
                                };
                                db.LopHocPhan_HocVienDbSet.Add(oX2);

                                BizNhatKyHoatDong.LogAndCommitUpdate2<LopHocPhan_HocVien>(oX, oX2, oX.MaHocVien, LOAIDOITUONG.LỚP_HỌC_PHẦN_HỌC_VIÊN, db);
                            }
                        }
                        trans.Commit();
                    }
                    catch (Exception exc)
                    {
                        trans.Rollback();
                        throw exc;
                    }
                }
            }
        }

        /// <summary>
        /// Đăng ký học phần cho học viên
        /// </summary>
        /// <param name="hocVien"></param>
        /// <param name="vaoLopHocPhan"></param>
        /// <param name="hocThayThe"></param>
        /// <param name="hocPhanThayThe"></param>
        /// <param name="lanHoc"></param>
        /// <param name="db"></param>
        internal static void DangKyHocVien(HocVien hocVien, LopHocPhan vaoLopHocPhan,
            bool hocThayThe, HocPhan hocPhanThayThe, int lanHoc, string ghiChu, CEMS4UG_DHKHContext db = null)
        {
            if (db == null)
                using (var db2 = CEMS4UG_DHKHContext.GetContext())
                    DangKyHocVien(hocVien, vaoLopHocPhan, hocThayThe, hocPhanThayThe, lanHoc, ghiChu, db2);
            else
            {
                // 1. Kiểm tra trong học kỳ này, học viên không đăng ký học học phần này
                var maHocKyGUID = vaoLopHocPhan.MaHocKyGUID;
                var maHocPhanGUID = vaoLopHocPhan.MaHocPhanGUID;
                var x = db.LopHocPhan_HocVienDbSet
                    .Include("LopHocPhan")
                    .Where(e =>
                        e.MaHocVien == hocVien.MaHocVien &&
                        (e.LopHocPhan.MaHocPhanGUID == vaoLopHocPhan.MaHocPhanGUID || e.MaHocPhanGUID_ThayThe == vaoLopHocPhan.MaHocPhanGUID) &&
                        e.LopHocPhan.MaHocKyGUID == vaoLopHocPhan.MaHocKyGUID)
                    .Select(e => e.LopHocPhan)
                    .FirstOrDefault();
                if (x != null)
                    throw new Exception(string.Format("Học viên đã đăng ký học tại lớp học phần {0}", x.TenLopHocPhanFull));

                // 2. Kiểm tra xem học viên chưa từng tích luỹ tín chỉ cho học phần này 

                // 3. Thực hiện ghi danh
                var y = new LopHocPhan_HocVien()
                {
                    MaLopHocPhanGUID = vaoLopHocPhan.MaLopHocPhanGUID,
                    MaHocVien = hocVien.MaHocVien,
                    HocThayThe = hocThayThe,
                    MaHocPhanGUID_ThayThe = hocThayThe ? hocPhanThayThe.MaHocPhanGUID : null,
                    LanHoc = lanHoc,
                    GhiChu = ghiChu
                };
                db.LopHocPhan_HocVienDbSet.Add(y);
                BizNhatKyHoatDong.LogAndCommitInsert2(y, y.MaLopHocPhan_HocVienGUID, LOAIDOITUONG.LỚP_HỌC_PHẦN_HỌC_VIÊN, db);
            }
        }
    }
}
